-- Author: roger
with Ada.Exceptions; use Ada.Exceptions;
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Strings; use Ada.Strings;
with Ada.Strings.Maps;      use Ada.Strings.Maps;


package body PajekFileProcess is
    
    procedure OpenAndReadNumberOfNodes (fileName: in String; InputFile: out File_Type; n: out Positive) is
        -- SectionTag Defines
        SectionTagLength : CONSTANT Integer := 9;
        SUBTYPE SectionTag IS String(1 .. SectionTagLength);
        SectionType : SectionTag;
    begin
        -- Open File
        Ada.Text_IO.Open(
            File => InputFile,
            Name => filename,
            Mode => Ada.Text_IO.In_File);
        -- Read Number of nodes
        IF NOT Ada.Text_IO.End_Of_File( InputFile ) then
            Ada.Text_IO.Get(File => InputFile, Item => SectionType);
            Ada.Integer_Text_IO.Get(File => InputFile, Item => n);
        END IF;   
    end OpenAndReadNumberOfNodes ;
    
    Procedure RemoveSpaces(s: in out String) is
        first: positive;
        last: positive;
    begin
        Find_Token (s, To_Set ("0123456789"), Inside, First, last);
        if first > 1 then
            tail(s, s'length-first+1, left, ' ');
        end if;
    end RemoveSpaces;
    
    Procedure ReadStringFromFile(f: in File_Type; s: out String) is
        last: Positive;
    begin
        Get_line(f,s,last);
        --Put_line("Get completed chars: " & Integer'Image(last));    
        RemoveSpaces(s);
    exception
        When others => Put_Line(Standard_Error, "Failed reading nodes line");
    end ReadStringFromFile;
    
    Procedure ReadNodeList(f: in File_Type; list: in out NodeListPointer) is
        first: Positive;
        ultim: Positive;
        s: String(1..MaxLineLength);
    begin
        -- Read Nodes
        Skip_Line(f);
        s:=(1..MaxLineLength => ' ');
        for i in 1..list.nNodes loop
            -- Read the entire line
            ReadStringFromFile(f,s);
            -- Find id bounds
            Find_Token (s, To_Set (space), Outside, First, ultim);
            list.nodes(i).id:=Integer'Value(head(s,1+ultim-first));
            -- Remove parsed parameter
            tail(s,MaxLineLength-2-(ultim-first),left,' ');
            -- Empty the name String
            list.nodes(i).Name:= (1..list.nodes(i).Name'Length => ' ');
            -- Find name bounds
            Find_Token (s, To_Set (space), Outside, First, ultim);
            -- Name is quoted                        
            if index(s,"""") = 1 then
                first:=first+1;
                ultim:=ultim-1;
                tail(s,MaxLineLength-1,left,' ');
            end if;
            -- Remove the rest of the line
            head(s,1+ultim-first,left,' ');
            Move (s,list.nodes(i).Name,right,left, ' ' );
            --list.nodes(i).Name:=To_Bounded_String(s);
            --list.nodes(i).Name:=s;
            --head(list.nodes(i).Name,1+ultim-first,left,' ');
            list.nodes(i).links:=0;
        end loop;
    exception 
            When E: others =>Put_Line(Exception_Name(E) & Exception_Message(E));
    end ReadNodeList;
    
    Procedure ReadEdgeList(f:in File_Type; list: in out NodeListPointer) is
        edges: String (1..20);
        last: Integer;
        
        -- Link definition
        Type Edge is RECORD
                startNode: Positive;
                EndNode: Positive;
                Value: Positive;
        end record;
        
        readEdge: Edge;
        
    begin
        --Create link list for each node
        for i in 1..list.nNodes loop
            list.nodes(i).linkList:=new linkArray(1..list.nNodes);
        end loop;
 
        --Read Edges Tag
        Get_Line(f, edges, last);
        --Read Links
        WHILE NOT Ada.Text_IO.End_Of_File( f ) LOOP
                Get(f, readEdge.StartNode);
                Get(f, readEdge.EndNode);
                Get(f, readEdge.Value);
                list.nodes(readEdge.StartNode).links := list.nodes(readEdge.StartNode).links+1;
                list.nodes(readEdge.EndNode).links := list.nodes(readEdge.EndNode).links+1;
                Skip_Line(f); --Skip the rest of the line
                -- fill link on startnode and end node
                list.nodes(readEdge.StartNode).linkList(list.nodes(readEdge.StartNode).links):=readEdge.EndNode;
                list.nodes(readEdge.EndNode).linkList(list.nodes(readEdge.EndNode).links):=readEdge.StartNode;
        end loop;    
    exception
        when e: others=>
            Put_Line(Standard_Error, "Recovered from premature end of file");
    end ReadEdgeList;
    
    function LoadPajekFile(filename: in String) return NodeListPointer is
        list : NodeListPointer;
        f: File_Type;
    begin
        list:=new NodeList;
        OpenAndReadNumberOfNodes (filename, f, list.nNodes);
        list.nodes:=new NodeArray(1..list.nNodes);
        ReadNodeList(f, list);
        ReadEdgeList(f,list);
        Close(f);
        return list;
    end LoadPajekFile;
    
    -- Protected Node Occupation
    protected body NodeOccupation is
        
                entry ocupe when free is
                begin
                    timesVisited:=timesVisited+1;
                    free:=false;
                end ocupe;
        
                procedure leave is
                begin
                    free:=true;
                end leave;
        
                function isFree return Boolean is
                begin
                    return free;
                end isFree;
        
                function nTimesVisited return Integer is
                begin
                    return timesVisited;
                end nTimesVisited;
        
      end NodeOccupation; 
    
begin
	null;
end PajekFileProcess;
